using System;
using System.Web;
using Tools.Common.ServiceLocator;
using Tools.Common.UnitOfWork;
using Tools.Common.UnitOfWork.Contracts;

namespace Web.App.Infrastructure.UnitOfWork
{
    public class UoWService
    {
        private const string UNIT_OF_WORK = "Application.UnitOfWork.Current";

        public static void InitializeUoW(Guid? id)
        {
            InitializeUoW(id, ConversationType.OneUoWPerRequest);
        }

        public static void InitializeUoW(Guid? id, ConversationType type)
        {
            IUnitOfWork unitOfWork = null;
            var uowRepository = ServiceLocator.Current.Resolve<IUnitOfWorkRepository>("UoWRepository");
            var uowFactory = ServiceLocator.Current.Resolve<IUnitOfWorkFactory>();

            if (id != null)
            {
                unitOfWork = uowRepository.PickupUnitOfWork(id);
            }

            if (unitOfWork == null)
            {
                unitOfWork = uowFactory.Create(type);
            }

            UnitOfWork.Current = unitOfWork;
        }

        public static void ReplaceCurrentUnitOfWork(IUnitOfWork unitOfWork)
        {
            UnitOfWork.Current = unitOfWork;
             
        }

        public static void FinalizeCurrentUoW()
        {
            var uowRepository = ServiceLocator.Current.Resolve<IUnitOfWorkRepository>();

            if (HttpContext.Current.Server.GetLastError() == null && UnitOfWork.Current.ConversationType == ConversationType.LongConversation)
            {
                UnitOfWork.AsSession.Disconnect();
                if (!IsAspSessionAvailable)
                {
                    throw new InvalidOperationException(
                        "Session must be enabled when using Long Conversations! If you are using web services, make sure to use [WebMethod(EnabledSession=true)]");
                }
                uowRepository.SaveUnitOfWork(UnitOfWork.Current);
            }
            else
            {
                UnitOfWork.Current.Dispose();
                //(HttpContext.Current.Items[UNIT_OF_WORK] as IUnitOfWork).Dispose();
            }
        }

        public static bool IsAspSessionAvailable
        {
            get
            {
                return HttpContext.Current.Session != null;
            }
        }

        public static IUnitOfWork GetExistingOrCreateNewUoW(Guid? id)
        {
            IUnitOfWork unitOfWork = null;
            var uowRepository = ServiceLocator.Current.Resolve<IUnitOfWorkRepository>();
            var uowFactory = ServiceLocator.Current.Resolve<IUnitOfWorkFactory>();

            if (id != null)
            {
                unitOfWork = uowRepository.PickupUnitOfWork(id);
            }

            if (unitOfWork == null)
            {
                unitOfWork = uowFactory.Create(ConversationType.OneUoWPerRequest);
            }

            return unitOfWork;
        }



    }
}